package com.mutouren.modules.datapush.remote;

import java.util.Date;

import org.apache.commons.lang3.StringUtils;
//import org.springframework.stereotype.Service;

import com.mutouren.common.utils.HttpClientUtils;
import com.mutouren.common.utils.HttpResult;
import com.mutouren.common.utils.JsonUtils;
import com.mutouren.modules.datapush.base.MethodType;
import com.mutouren.modules.datapush.base.PushMessage;
import com.mutouren.modules.datapush.base.PushStatus;
import com.mutouren.modules.datapush.dao.PushMessageDao;
import com.mutouren.modules.datapush.dao.impl.DaoFactoryImpl;
import com.mutouren.modules.datapush.server.AbstractServer;
import com.mutouren.modules.datapush.strategy.ConcurrentStrategy;
import com.mutouren.modules.datapush.strategy.RemoteConcurrentStrategyManager;
import com.mutouren.modules.datapush.strategy.RemoteRepeatStrategyManager;
import com.mutouren.modules.datapush.strategy.RepeatStrategy;

//@Service
public class RemotePushServer extends AbstractServer {
	
	//@Value("${datapush.sender.maxPermitCacheSize:1000000}")
	//private final static int maxPermitSize_Send = 1000000;
	//@Value("${datapush.sender.maxThreadSize:20}")
	//private final static int maxThreadSize_Send = 20;	
	
	//@Resource
	private PushMessageDao pushMessageDao = DaoFactoryImpl.getInstance().getPushMessageDao();

	public RemotePushServer(int maxPermitSize, int maxThreadSize) {
		super("RemotePushServer", maxThreadSize);
		this.maxPermitSize = maxPermitSize;
		init();
	}
	
	private void init() {
		this.concurrentStrategyManager = new RemoteConcurrentStrategyManager();
		this.repeatStrategyManager = new RemoteRepeatStrategyManager();
	}
	
	@Override
	protected void onFinish(PushMessage message) {
		try {
			if (message.getPushStatus() != PushStatus.SUCCESS) {
				pushMessageDao.updateFinish(message);
			}
		} catch (Throwable t) {
			errorLogger.error("RemotePushServer onFinish error: " + message.getId());
		}
	}	

	@Override
	protected void send(PushMessage message) {
		try {
			// get data
			PushMessage tempMessage = pushMessageDao.get(message.getId());
			if(tempMessage == null) {
				// no find message, direct discard it
				message.setPushStatus(PushStatus.SUCCESS);
				return;
			}			
			message.setUrl(tempMessage.getUrl());
			message.setRequestBody(tempMessage.getRequestBody());
			message.setVersion(tempMessage.getVersion());
			
			// update status
			pushMessageDao.updateProcessing(message);
			
			message.setRequestCount(message.getRequestCount() + 1);
			message.setLastUpdateTime(new Date());
		} catch(Throwable t) {	
			message.thinData();
			throw t;
		}
		
		try {
			sendHttpRequest(message);
			
			// update result
			pushMessageDao.updateResult(message);
		} finally {
			message.thinData();
		}
	}
	
	private void sendHttpRequest(PushMessage message) {				
		HttpClientUtils httpClient = new HttpClientUtils(message.getRealUrl(), message.getMethodType().name);
		try {
			if ((message.getMethodType() == MethodType.POST)&&(!StringUtils.isBlank(message.getRequestBody()))) {
				httpClient.setBody(message.getRequestBody(), message.getCharset().name, message.getContentType().name);
			}
			
			HttpResult httpResult = httpClient.execute();
			if(httpResult.isSuccess()) {
				String tempBody = httpResult.getContent(message.getCharset().name);
				message.setResponse(tempBody);
				if (checkSuccessFlag(message.getMethodAlias(), tempBody)) {
					message.setPushStatus(PushStatus.SUCCESS);
					message.setIsFinish(true);
					
				} else {
					message.setPushStatus(PushStatus.FAIL);
				}				
			} else {
				message.setPushStatus(PushStatus.FAIL);
				message.setResponse(StringUtils.substring(httpResult.toString(message.getCharset().name), 0, 200));
			}						
		} catch (Throwable t) {
			message.setPushStatus(PushStatus.EXCEPTION);
			message.setResponse(StringUtils.substring(t.getMessage(), 0, 100));			
			errorLogger.error(this.getServerAlias() + " send pushMessage error", t);
		} finally {
			//sendLogger.debug(String.format("serverAlias:%s, message:%s", this.getServerAlias(), JSON.toJSONString(message)));
			sendLogger.debug("RemotePushServer send package:" + JsonUtils.beanToJson(message));
		}
				
	}

	@Override
	public void receive(PushMessage message) {
		message.thinData();
		super.receive(message);
	}
	
	public boolean isPermitReceive(int dataSize) {		
		return this.maxPermitSize - this.getQueueSize() - dataSize - 100 > 0 ? true : false;
	}
	
	@Override
	public void addConcurrentStrategy(ConcurrentStrategy strategy) {
		throw new IllegalArgumentException("in remote mode, not permit add concurrentStrategy");
	}	
	@Override
	public void addRepeatStrategy(RepeatStrategy strategy) {
		throw new IllegalArgumentException("in remote mode, not permit add repeatStrategy");
	}	
}
